package agents.tourguideagentbehaviours;

import java.util.ArrayList;
import java.util.HashMap;

import resource.Artifact;

import agents.CuratorAgent;
import agents.TourGuideAgent;

import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.FSMBehaviour;
import jade.core.behaviours.OneShotBehaviour;
import jade.core.behaviours.SequentialBehaviour;
import jade.core.behaviours.SimpleBehaviour;
import jade.core.behaviours.TickerBehaviour;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.UnreadableException;

public class FindTourForUserBehaviour extends SequentialBehaviour{
	TourGuideAgent owner;
	AID curatorAgent;
	HashMap<String, Artifact> artifacts;
	
	public FindTourForUserBehaviour(TourGuideAgent owner){
		this.owner = owner;
		
		addSubBehaviour(new FindCuratorBehaviour(myAgent, 1000));
		addSubBehaviour(new GetArtifactsFromCuratorBehaviour());
		addSubBehaviour(new CalculateTourBehaviour());
	}
	
	class FindCuratorBehaviour extends TickerBehaviour{

		public FindCuratorBehaviour(Agent a, long period) {
			super(a, period);
		}

		@Override
		protected void onTick() {
			DFAgentDescription dfd = new DFAgentDescription();
	        ServiceDescription sd  = new ServiceDescription();
	        sd.setType("getAllArtifacts");
	        dfd.addServices(sd);
	        
	        DFAgentDescription[] result = null;
			try{
				result = DFService.search(myAgent, dfd);
			}catch (FIPAException e){
				throw new RuntimeException(e);
			}
			
			if(result.length > 0){
				curatorAgent = result[0].getName();
				stop();
			}
		}
	}
	
	class GetArtifactsFromCuratorBehaviour extends FSMBehaviour{
		private static final String STATE_A = "A";
		private static final String STATE_B = "B";		
		public GetArtifactsFromCuratorBehaviour(){
			this.registerFirstState(new SendArtifactRequestBehaviour(), STATE_A);
			this.registerLastState(new RecieveArtifactsFromCuratorBehaviour(), STATE_B);
			this.registerDefaultTransition(STATE_A, STATE_B);
		}
		
		class SendArtifactRequestBehaviour extends OneShotBehaviour{
			@Override
			public void action() {
				ACLMessage message = new ACLMessage(CuratorAgent.GET_ARTIFACTS_SERVICE);
				message.addReceiver(curatorAgent);
				message.setSender(owner.getAID());
				owner.send(message);
			}
		}
		
		class RecieveArtifactsFromCuratorBehaviour extends SimpleBehaviour{
			boolean done = false;
			
			@SuppressWarnings("unchecked")
			public void action() {
				MessageTemplate template = MessageTemplate.and(MessageTemplate.MatchPerformative(ACLMessage.INFORM),
																MessageTemplate.MatchSender(curatorAgent));
				ACLMessage msg = myAgent.receive(template);
				if(msg != null){
					try{
						artifacts = (HashMap<String, Artifact>) msg.getContentObject();
					}catch(UnreadableException e){
						throw new RuntimeException(e);
					}
					done = true;
				}
				else{
					block();
				}
			}

			public boolean done() {
				return done;
			}
		}		
	}
	
	class CalculateTourBehaviour extends OneShotBehaviour{
		@Override
		public void action() {
			ArrayList<String> tour = new ArrayList<String>();
			ArrayList<String> interests = owner.getUser().getInterests();
			ArrayList<String> visitedArtifacts = owner.getUser().getVisitedArtifact();
			for(String key : artifacts.keySet()){
				if(interests.contains(artifacts.get(key).getGenre()) && 
						!visitedArtifacts.contains(artifacts.get(key).getName())){
					tour.add(key);
				}
			}
			
			String[] stringList = new String[tour.size()];
			tour.toArray(stringList);
			
			owner.setTour(stringList);
		}
	}
}
